package com.ch.web.config.websocket;


import com.alibaba.fastjson.JSON;
import com.ch.web.enums.SessionEnum;
import com.ch.web.service.XyUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestParam;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;


@ServerEndpoint("/webSocket/{username}")
@Component
@Lazy
public class WebSocketServer {
    private static XyUserService xyUserService;
    @Autowired
    public void setXyUserService(XyUserService xyUserService) {
        WebSocketServer.xyUserService = xyUserService;
    }
    //静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
    private static AtomicInteger onlineNum = new AtomicInteger();

    //concurrent包的线程安全Set，用来存放每个客户端对应的WebSocketServer对象。 string 代表的是账号
    private static ConcurrentHashMap<String, SessionCode> sessionPools = new ConcurrentHashMap<>();


    //发送消息
    public void sendMessage(Session session, String message) throws IOException {
        if (session != null) {
            synchronized (session) {
                System.out.println("发送数据：" + message);
                session.getBasicRemote().sendText(message);
            }
        }
    }

    //给指定用户发送信息
    public void sendInfo(String userName, String message) {
        Session session = sessionPools.get(userName).getSession();
        try {
            sendMessage(session, message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 群发消息
    public void broadcast(String message) {
        for (SessionCode code : sessionPools.values()) {
            try {
                sendMessage(code.getSession(), message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    //建立连接成功调用
    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) throws IOException {
        SessionCode code = sessionPools.get(username);
        if (null == code) {
            System.out.println(username+"上线了");
            sessionPools.put(username, new SessionCode(session, SessionEnum.CODE_1.getCode()));
            addOnlineCount();
            System.out.println(username + "加入webSocket！当前人数为" + onlineNum);
        } else {
            //不为空 想多不要想 这肯定是有人了 在线呗  发送前端 告诉它 你已经被下线了
            code.getSession().getBasicRemote().sendText("2");
            sessionPools.remove(username);
            decOnlineCount();
            //代表当前这个人是上线者
            sessionPools.put(username, new SessionCode(session, SessionEnum.CODE_2.getCode()));
            addOnlineCount();
            System.out.println(username + "加入webSocket！当前人数为" + onlineNum);
        }
    }

    //关闭连接时调用
    @OnClose
    public void onClose(@PathParam(value = "username") String userName) {
        SessionCode code = sessionPools.get(userName);
        Integer code1 = code.getCode();
        if (code1 == 1) {
            //正常一个人登录的直接剔除
            xyUserService.logout(userName);
            sessionPools.remove(userName);
            subOnlineCount();
            System.out.println(userName + "断开webSocket连接！当前人数为" + onlineNum);
        } else {
            //不是的 强制上线的 说明 另外一个人被踢了 不做任何处理  这个代表是被人强制下线的session
        }
    }

    //收到客户端信息后，根据接收人的username把消息推下去或者群发
    // to=-1群发消息
    @OnMessage
    public void onMessage(@RequestParam String message, Session session) throws IOException {
        //必须进行一个综合的校验码
        WebSocketMessage webSocketMessage = JSON.parseObject(message, WebSocketMessage.class);
        int parseInt = webSocketMessage.getCode();
        switch (parseInt) {
            case 1:
                break;
            case 2:
                //这是客户端手动关闭当前的这个连接
                System.out.println(message);
                session.close();
        }
    }

    //错误时调用
    @OnError
    public void onError(Session session, Throwable throwable) {
        System.out.println("发生错误");
        throwable.printStackTrace();
    }

    public void addOnlineCount() {
        onlineNum.incrementAndGet();
    }

    public void decOnlineCount() {
        onlineNum.decrementAndGet();
    }

    public void subOnlineCount() {
        onlineNum.decrementAndGet();
    }

    public AtomicInteger getOnlineNumber() {
        return onlineNum;
    }

    public ConcurrentHashMap<String, SessionCode> getSessionPools() {
        return sessionPools;
    }
}
